/**----------------------------------------
 * @description 消息管理基类
 * @author      lxc
 * @file        MsgMgr.ts
 * @Date        2022-05-05
 * @version     1.0.0
 * ----------------------------------------
 */

import { LogClass } from "../LogClass";

/**
 * 消息类型
 */
export enum MsgType {
    UI,  /** UI */
    Net, /** 网络消息 */
}

/**
 * 消息监听数据结构
 */
export interface ListenerData {
    priority: number,      /** 优先级 */
    swallow: boolean,      /** 吞噬消息 */
    msgType: MsgType,      /** 消息类型 */
    msgName: string | number,/** 消息名 */
    callBack: Function,      /** 回调函数 */
}

/**
 * @description 消息管理基类，可根据消息类型创建多个消息管理器
 * @funcionts 消息监听/消息派发/监听移除
 */
export class MsgMgr extends LogClass {
    /**
     * 输出log 前缀
     */
    protected logPrefix: string = "MsgMgr";
    /**
     * 当前管理器的消息监听列表
     */
    private msgListeners: { [msgName: string | number]: ListenerData[] } = {}
    /**
     * 管理的消息类型
     * 默认类型为 ui 消息管理器
     */
    private mgrMsgType: MsgType = MsgType.UI;
    /**
     * @param msgType 创建时制定管理器管理的消息类型
     */
    constructor(msgType: MsgType) {
        super()
        this.mgrMsgType = msgType;
        this.msgListeners = {};
    }
    /**
     * 添加消息监听至消息管理容器
     * @param msgName 消息名
     * @param callBack 消息处理回调
     * @param priority 优先级
     * @param swallow 吞噬消息
     * @returns 消息被监听的数据结构
     */
    addListener(msgName: string | number, callBack: Function, priority: number = 0, swallow: boolean = false): ListenerData {
        // 一个消息可以多处监听
        if (!this.msgListeners[msgName]) {
            this.msgListeners[msgName] = [];
        }
        // 优先级越大则先处理消息
        priority = priority > 0 ? priority : - this.msgListeners[msgName].length

        let listener: ListenerData = {
            msgName,
            callBack,
            priority,
            swallow,
            msgType: this.mgrMsgType
        }
        this.msgListeners[msgName].push(listener)

        this.msgListeners[msgName].sort(function (a, b) {
            return b.priority - a.priority // 优先级从大到小排序
        })

        return listener;
    }
    /**
     * 从消息列表中移除指定监听
     * @param listener 
     */
    removeListener(listener: ListenerData) {
        let listeners = this.msgListeners[listener.msgName]
        if (listeners && listeners.length > 0) {
            for (let i = listeners.length - 1; i >= 0; i--) {
                if (listeners[i].callBack === listener.callBack) {
                    listeners.splice(i, 1);
                }
            }
        } else {
            this.printError("removeListener unfind msgName")
        }
    }
    /**
     * 消息广播
     * @param msgName 
     * @param args 
     */
    dispatchMsg(msgName: string | number, ...args) {
        this.printLog("dispatch", msgName);
        if (this.msgListeners[msgName]?.length > 0) {
            for(let listener of this.msgListeners[msgName]){
                /** apply 第一个参数是 this 作用于，第二个参数是参数数组 */
                listener.callBack.apply(null,args)
                if(listener.swallow)break;
            }
        }
    }
}
